///************************************************************************
/// <copyrigth>2018-2019 Corporation.All Rights Reserved</copyrigth>
/// <author>tangyingzhong</author>
/// <contact>tangyz114987@outlook.com</contact>
/// <version>v1.0.0</version>
/// <describe>
/// It supports http,https,ftp communications
///</describe>
/// <date>2020/5/30</date>
///***********************************************************************
#ifndef ITYZLIBCURL_H
#define ITYZLIBCURL_H

#include <string>
#include <vector>
#include <map>

typedef int(*UploadProgress)(void* pUserData,
	double TotalToUpload,
	double NowUpload);

typedef int(*DownLoadProgress)(void* pUserData,
	double TotalToDown,
	double NowDownload);

struct FileInfo
{
	// Is directory or file
	bool bIsDirectory;

	// File path
	std::string strFilePath;

	// File name
	std::string strFileName;

	// File size
	long iFileSize;

	// Modify time
	int iFileModifyTime;

	// File modify time
	std::string strFileModifyTime;

	FileInfo()
	{
		bIsDirectory = false;

		strFilePath = "";

		strFileName = "";

		iFileSize = 0;

		iFileModifyTime = 0;

		strFileModifyTime = "";
	}
};

enum ContentTypeEnum
{
	// application/json
	APP_JSON=0,

	// application/x-www-form-urlencoded
	APP_FORM_ENCODE,

	// multipart/form-data(Used for uploading file by http)
	MULTI_FORM_DATA,

	// text/xml
	TEXT_XML,

	// text/html
	TEXT_HTML,

	// application/octet-stream(binary)
	BINARY_STREAM
};

enum ContentChartSetEnum
{
	// Unicode(Support all countries' language)
	CHARSET_UNICODE=0,

	// UTF-8(Uicode's upgrade version)
	CHARSET_UTF8,

	// GB2312(Ansi code not including traditional chinese)
	CHARSET_GB2312,

	// GBK(GB2312's extend version including traditional chinese)
	CHARSET_GBK
};

class ITyzLibCurl
{
public:
	// Detructe the ITyzLibCurl
	virtual ~ITyzLibCurl() {	}

public:
	///************************************************************************
	/// <summary>
	/// Set time out
	/// </summary>
	/// <param name=int iSeconds>Timeout(s)</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: it is for one time curl request setting
	/// </remarks>
	///***********************************************************************
	virtual void SetTimeout(int iSeconds = 60) = 0;

	///************************************************************************
	/// <summary>
	/// Set try count
	/// </summary>
	/// <param name=int iCount>Try count if operation failed</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: it is for one time curl request setting
	/// </remarks>
	///***********************************************************************
	virtual void SetTryCount(int iCount = 3) = 0;

	///************************************************************************
	/// <summary>
	/// Get the current libcurl version
	/// </summary>
	/// <returns></returns>
	/// <remarks>
	/// none
	/// </remarks>
	///***********************************************************************
	virtual std::string GetCurVersion() = 0;

	///************************************************************************
	/// <summary>
	/// Set upload callback function
	/// </summary>
	/// <param name=UploadProgress pUploadFunc>User callback funtion</param>
	/// <param name=void * pUserData>User's data</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: you can get upload progress by this callback function
	/// </remarks>
	///***********************************************************************
	virtual void SetUploadFunc(UploadProgress pUploadFunc = NULL, void* pUserData = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Set download callback function
	/// </summary>
	/// <param name=pUploadFunc>User callback funtion</param>
	/// <param name=pUserData>User's data</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: you can get download progress by this callback function
	/// </remarks>
	///***********************************************************************
	virtual void SetDownloadFunc(DownLoadProgress pDownloadFunc = NULL, void* pUserData = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Set head info for requesting
	/// </summary>
	/// <param name=std::string strContentType>Content type of your body data</param>
	/// <param name=std::string strEncodeType>Encode type of your body data</param>
	/// <returns></returns>
	/// <remarks>
	/// none
	/// </remarks>
	///***********************************************************************
	virtual void SetRequestHead(ContentTypeEnum eContentType = APP_JSON,
		ContentChartSetEnum eCharSet = CHARSET_UTF8) = 0;

	///************************************************************************
	/// <summary>
	/// Get the error std::string
	/// </summary>
	/// <param name=iErrorCode>Error code</param>
	/// <param name=strErrorMsg>Error message</param>
	/// <returns></returns>
	/// <remarks>  
	/// none
	/// </remarks>
	///***********************************************************************
	virtual void GetErrorInfo(int& iErrorCode, std::string& strErrorMsg) = 0;

	///************************************************************************
	/// <summary>
	/// Get the respond by http or https 
	/// </summary>
	/// <param name=strRequestUrl>Url</param>
	/// <param name=strResponseData>Respond data</param>
	/// <param name=pRequestMap>Request data which will be appended to the url</param>
	/// <param name=pCaPath>Certificatation path</param>
	/// <returns>Respond data</returns>
	/// <remarks>
	/// Note: It support GBK string input not utf8! pCaPath==NULL : do not verify the certification on server
	/// </remarks>
	///***********************************************************************
	virtual bool Get(std::string strRequestUrl,
		std::string& strResponseData,
		std::map<std::string, std::string>* pRequestMap = NULL,
		const char* pCaPath = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Post the request by http or https(application/json)
	/// </summary>
	/// <param name=strRequestUrl>Url</param>
	/// <param name=strRequestJsonData>Request json data</param>
	/// <param name=strResponseData>Respond data</param>
	/// <param name=pCaPath>Certificatation path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: It support GBK string input not utf8! pCaPath==NULL : do not verify the certification on server
	/// </remarks>
	///***********************************************************************
	virtual bool Post(std::string strRequestUrl,
		std::string strRequestJsonData,
		std::string& strResponseData,
		const char* pCaPath = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Post the request by http or https(application/x-www-form-urlencoded)
	/// </summary>
	/// <param name=std::string strRequestUrl>URL</param>
	/// <param name=std::string & strResponseData>Repsond data</param>
	/// <param name= pRequestMap> </param>
	/// <param name=const char * pCaPath>Certificatation file path</param>
	/// <returns></returns>
	/// <remarks>
	/// Post the data with application/x-www-form-urlencoded
	/// It support GBK string input not utf8! 
	/// Note: pCaPath==NULL : do not verify the certification on server
	/// </remarks>
	///***********************************************************************
	virtual bool Post(std::string strRequestUrl,
		std::string& strResponseData,
		std::map<std::string, std::string>* pRequestMap = NULL,
		const char* pCaPath = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Upload file (application/octet-stream)
	/// </summary>
	/// <param name=std::string strRequestUrl>URL</param>
	/// <param name=std::string & LocalFileTable>Local files' full path</param>
	/// <param name=std::string & strRespondData>Respond data to tell you upload result</param>
	/// <param name=const char * pCaPath>Certificatation file path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: It support GBK string input not utf8! pCaPath==NULL : do not verify the certification on server
	/// </remarks>
	///***********************************************************************
	virtual bool UploadFile(std::string strRequestUrl,
		std::vector<std::string>& LocalFileTable,
		std::string& strRespondData,
		const char* pCaPath = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Dwnload file (application/octet-stream)
	/// </summary>
	/// <param name=std::string strRequestUrl>URL</param>
	/// <param name=std::string & strFilePath>File path which will be uploaded</param>
	/// <param name=std::string & strRespondData>Respond data to tell you upload result</param>
	/// <param name=const char * pCaPath>Certificatation file path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: It support GBK string input not utf8! pCaPath==NULL : do not verify the certification on server
	/// </remarks>
	///***********************************************************************
	virtual bool DownloadFile(std::string strRequestUrl,
		std::string strLocalSaveFilePath,
		const char* pCaPath = NULL) = 0;

	///************************************************************************
	/// <summary>
	/// Connect to FTP
	/// </summary>
	/// <param name=strRemoteIpAddr>FTP ip address</param>
	/// <param name=strUserName>Login user name</param>
	/// <param name=strPassword>Login password</param>
	/// <param name=strPortNo>FTP port no</param>
	/// <returns></returns>
	/// <remarks>
	/// It support GBK string input not utf8! 
	/// Note: FTP's ip address such as 127.0.0.1 and it's portNo is 21 at the most time so you can keep it default.
	/// </remarks>
	///***********************************************************************
	virtual bool FtpConnect(const std::string strRemoteIpAddr,
		const std::string strUserName,
		const std::string strPassword,
		const std::string strPortNo = "21") = 0;
 
	///************************************************************************
	/// <summary>
	/// List all files under the directory
	/// </summary>
	/// <param name=strRemoteDirPath>FTP directory path</param>
	/// <param name=FileInfoTable>All files' info under the dir</param>
	/// <returns></returns>
	/// <remarks>
	/// Note:It support GBK string input not utf8!  FTP directory path just like /Test/12/
	/// </remarks>
	///***********************************************************************
	virtual bool FtpList(const std::string strRemoteDirPath, std::vector<FileInfo>& FileInfoTable) = 0;

	///************************************************************************
	/// <summary>
	/// Get file info on ftp
	/// </summary>
	/// <param name=strRemoteDirPath>FTP file path</param>
	/// <returns>File information</returns>
	/// <remarks>
	/// Note:It support GBK string input not utf8! 
	/// </remarks>
	///***********************************************************************
	virtual bool GetFtpFileInfo(const std::string strRemoteFilePath, FileInfo& Info) = 0;

	///************************************************************************
	/// <summary>
	/// Upload file to the FTP
	/// </summary>
	/// <param name=strRemoteDirPath>FTP directory path</param>
	/// <param name=strLocalFilePath>Local file's full path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: strRemoteDirPath like /test . 
	/// Local file's name can't contain " ".
	/// Support uploading from breakpoint
	/// It support GBK string input not utf8! 
	/// </remarks>
	///***********************************************************************
	virtual bool FtpUpload(const std::string strRemoteDirPath, const std::string strLocalFilePath) = 0;

	///************************************************************************
	/// <summary>
	/// Download file from FTP
	/// </summary>
	/// <param name=strRemoteFilePath>FTP file's full path</param>
	/// <param name=strLocalDirPath>Local file's full path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: Local file's name can't contain " ".
	/// Support downloading from breakpoint
	/// It support GBK string input not utf8! 
	/// </remarks>
	///***********************************************************************
	virtual bool FtpDownload(const std::string strRemoteFilePath, const std::string strLocalDirPath) = 0;

	///************************************************************************
	/// <summary>
	/// Upload directory to FTP
	/// </summary>
	/// <param name=strRemoteDirPath>FTP directory path</param>
	/// <param name=strLocalDirPath>Local directory full path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note:It support GBK string input not utf8! 
	/// </remarks>
	///***********************************************************************
	virtual bool FtpUploadDir(const std::string strRemoteDirPath,const std::string strLocalDirPath) = 0;

	///************************************************************************
	/// <summary>
	/// Download directory from FTP
	/// </summary>
	/// <param name=strRemoteDirPath>FTP directory full path</param>
	/// <param name=strLocalDirPath>Local directory full path</param>
	/// <returns></returns>
	/// <remarks>
	/// Note: There can't be file's name containing " "
	/// It support GBK string input not utf8!
	/// </remarks>
	///***********************************************************************
	virtual bool FtpDownloadDir(const std::string strRemoteDirPath, const std::string strLocalDirPath) = 0;
};

#endif // ITYZLIBCURL_H
